﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using IrrKlang;
using System.Data.SqlServerCe;
using System.Threading;
using System.IO;
using System.Windows.Controls;


namespace MercuryFE
{
    public class SoundHandler
    {
        public delegate void StartingNextTrackHandler(int trackId);
        public event StartingNextTrackHandler StartingNextTrack;

        private bool _isPlaying = false;
        public bool IsPlaying { get{return _isPlaying; } set{ _isPlaying = value;} }

        private static MediaElement _musicPlayer = null;

        public enum AddToQueueType
        {
            Top, Bottom, Replace
        }

        //ISoundEngine _soundEngine;

        List<QueueTrack> _queue;
        int _currentQueueId = -1;
        //ISound _currentlyPlaying = null;
       // TrackFinishedHandler _finishedHandler = null;

        public SoundHandler(MediaElement mediaElement)
        {
            _musicPlayer = mediaElement; // new MediaElement();
            _musicPlayer.LoadedBehavior = MediaState.Manual;
            _musicPlayer.IsMuted = false;
            _musicPlayer.MediaEnded += new System.Windows.RoutedEventHandler(_musicPlayer_MediaEnded);
            _musicPlayer.MediaFailed += new EventHandler<System.Windows.ExceptionRoutedEventArgs>(_musicPlayer_MediaFailed);

            // initialise the sound engine, with default parameters - MULTITHREADED...
            //_soundEngine = new ISoundEngine();
            //_queue = new List<QueueTrack>();
            //_finishedHandler = new TrackFinishedHandler(this);
        }

        void _musicPlayer_MediaFailed(object sender, System.Windows.ExceptionRoutedEventArgs e)
        {
            throw new NotImplementedException();
        }



        private void fadeVolume(bool isFadeIn)
        {
            if (isFadeIn)
            {
                _musicPlayer.Volume = 0f;
                if (_musicPlayer.Source != null)
                {
                    _musicPlayer.Play();
                    _isPlaying = true;
                }
 
                for (float i = 0; i <= 1; i += 0.1f)
                {
                    Thread.Sleep(200);
                    _musicPlayer.Volume = i;
                }


                //_soundEngine.SoundVolume = 0;

                //_soundEngine.SetAllSoundsPaused(false);

                //for (float i = 0; i <= 1; i += 0.1f)
                //{
                //    Thread.Sleep(200);
                //    _soundEngine.SoundVolume = i;
                //}
            }
            else
            {
                for (float i = 1; i >= 0; i -= 0.1f)
                {
                    Thread.Sleep(200);
                    _musicPlayer.Volume = i;
                }

                if (_musicPlayer.Source != null)
                {
                    _musicPlayer.Pause();
                    _isPlaying = false;
                }

                //for (float i = 1; i >= 0; i -= 0.1f)
                //{
                //    Thread.Sleep(200);
                //    _soundEngine.SoundVolume = i;
                //}
                //_soundEngine.SetAllSoundsPaused(true);
            }

        }

        public void pause()
        {
            // fade out, and stop all tracks...
            fadeVolume(false);
        }

        public void resume()
        {
            fadeVolume(true);
        }


        public void start()
        {
            if (_queue.Count > 0)
            {
                fadeVolume(true);
                playNextTrack(); //null);

            }
        }

        public void playNextTrack() //QueueTrack prevTrack)
        {
            if (_queue.Count == 0)
                return;


            // change status of last track played
            //if (prevTrack != null)
            if(_musicPlayer.Source != null)
            {
                foreach (QueueTrack qtc in _queue)
                {
                    if ( getTrackFile(qtc.TrackId) == _musicPlayer.Source.AbsoluteUri)
                    {
                        qtc.HasPlayed = true;
                        qtc.TrackPosition = -1;
                        break;
                    }
                }
            }




            // now get next track in queue
            QueueTrack qt = null;

            for (int i = 0; i < _queue.Count; i++)
            {
                if (_queue[i].HasPlayed == false)
                {
                    _currentQueueId = i;
                    qt = _queue[i];
                    break;
                }
            }

            // more tracks in queue.. so kick off
            if (qt != null)
            {
                string trackFile = getTrackFile(qt.TrackId);
                if (trackFile != null && File.Exists(trackFile))
                {
                    _musicPlayer.Source = new Uri(trackFile);
                    _musicPlayer.Volume = 1;
                    _musicPlayer.Play();
                    _isPlaying = true;



                    //_currentQueueId = qt.QueueId;
                    //_currentlyPlaying = _soundEngine.Play2D(trackFile);
                    //_currentlyPlaying.setSoundStopEventReceiver(new TrackFinishedHandler(this), qt);

                    StartingNextTrack(qt.TrackId);
                }
            }
            else
            {
                // reset the queue
                foreach (QueueTrack qtr in _queue)
                {
                    qtr.HasPlayed = false;
                    qtr.TrackPosition = -1;
                }
                playNextTrack(); //null);
            }
        }

        private string getTrackFile(int trackId)
        {
            string track = null;
            using (SqlCeConnection ceConn = new SqlCeConnection(ClientLib.getConnectionString()))
            {
                ceConn.Open();
                using (LauncherDB db = new LauncherDB(ceConn)) // linq
                {

                    track = (from t in db.JBTrack
                                where t.JBTrackID == trackId
                                select t.TrackFile).Single();
                }
            }
            return track;
        }

        public void clearQueue()
        {
            _musicPlayer.Stop();
            _musicPlayer.Source = null;

            //_soundEngine.StopAllSounds();
            //_soundEngine.RemoveAllSoundSources();
            _queue.Clear();
            _currentQueueId = -1;
        }

        public void addTrackToQueue(int trackId, bool addAtStart)
        {
            bool startPlaying = (_queue.Count > 0 ? false : true);
            
            QueueTrack q = new QueueTrack()
            {
                 TrackId = trackId
                 , HasPlayed = false
                 , TrackPosition = -1
            };

            if (!addAtStart)
                _queue.Add(q);
            else
            {
                _queue.Insert(0, q);
                _currentQueueId++;
            }

            if (startPlaying)
            {
                fadeVolume(true);
                playNextTrack(); //null);
            }
        }

        public void addCollectionToQueue(int collectionId, AddToQueueType addType) // top,bottom,replace
        {
            using (SqlCeConnection ceConn = new SqlCeConnection(ClientLib.getConnectionString()))
            {
                ceConn.Open();
                using (LauncherDB db = new LauncherDB(ceConn)) // linq
                {

                    if (addType == AddToQueueType.Replace)
                    {
                        clearQueue();
                    }


                    // get all the tracks in the collection
                    List<int> trackIds = (from c in db.JBCollection
                                 join ct in db.JBCollectionTrack on c.JBCollectionID equals ct.JBCollectionID
                                 join t in db.JBTrack on ct.JBTrackID equals t.JBTrackID
                                 where c.JBCollectionID == collectionId
                                 select t.JBTrackID).ToList();

                    bool addToStart = (addType== AddToQueueType.Top?true:false);
                    foreach (int trackId in trackIds)
                    {
                        addTrackToQueue(trackId, addToStart);
                    }
                }
            }
        }

        public void loadTracksFromDBQueue()
        {
         
            using (SqlCeConnection ceConn = new SqlCeConnection(ClientLib.getConnectionString()))
            {

                ceConn.Open();

                using (LauncherDB db = new LauncherDB(ceConn)) // linq
                {

                    _queue = (from q in db.JBQueue
                             join t in db.JBTrack on q.JBTrackID equals t.JBTrackID
                             orderby q.JBQueueID
                             select new QueueTrack {
                                  //QueueId = q.JBQueueID
                                    TrackId = t.JBTrackID
                                  ,  HasPlayed = ( q.HasPlayed==1?true:false)
                                  , TrackPosition =  q.TrackPosition 
                             }
                            ).ToList();

                    
                }
            }
            playNextTrack(); //null);
        }

        public void saveTracksToDBQueue(bool ClearMemoryAfterSave)
        {
            using (SqlCeConnection ceConn = new SqlCeConnection(ClientLib.getConnectionString()))
            {

                ceConn.Open();
                string error = "";
                ClientLib.truncateTable(ceConn, "JBQueue", "JBQueueID", ref error);
                using (LauncherDB db = new LauncherDB(ceConn)) // linq
                {
                    // clear out queue table first
                    //db.JBQueue.DeleteAllOnSubmit((from q in db.JBQueue select q).ToList());
                    //db.SubmitChanges();

                    foreach (QueueTrack track in _queue)
                    {
                        JBQueue q = new JBQueue()
                        {
                             JBTrackID = track.TrackId
                             , HasPlayed = (byte)(track.HasPlayed?1:0)
                             , TrackPosition = (track.HasPlayed?-1:track.TrackPosition)
                        };
                        db.JBQueue.InsertOnSubmit(q);
                    }
                    db.SubmitChanges();
                 
                }
            }

            if (ClearMemoryAfterSave)
                this.clearQueue();

        }

        void _musicPlayer_MediaEnded(object sender, System.Windows.RoutedEventArgs e)
        {
            playNextTrack();
        }

    }





    //public class TrackFinishedHandler : ISoundStopEventReceiver
    //{
    //    private SoundHandler _parent = null;

    //    public TrackFinishedHandler(SoundHandler parent)
    //    {
    //        _parent = parent;
    //    }

    //    public void OnSoundStopped(ISound sound, StopEventCause reason,  object userData)
    //    {
    //        _parent.playNextTrack((QueueTrack) userData);
    //    }

    //}

    public class QueueTrack
    {
        //public int QueueId { get; set; }
        public int TrackId { get; set; }
        public bool HasPlayed { get; set; }
        public int TrackPosition {get; set;}
    }
}
